package com.cdg.polymeric.core.ext.feign;

import com.cdg.polymeric.Excutor;
import com.cdg.polymeric.ReflectUtils;
import com.cdg.polymeric.RemoteClassNotMatchException;
import com.cdg.polymeric.annonation.Polymeric;
import com.cdg.polymeric.config.AnnotationSetting;
import com.cdg.polymeric.config.ClassAnnotationProperties;
import com.cdg.polymeric.config.ClassAnnotationSetting;
import com.cdg.polymeric.core.ext.excutor.AbstactFeignTemplateExcutor;
import com.cdg.polymeric.core.ext.excutor.ExcutorResultMatcher;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 聚合feign 客户端 数据源实现
 */
public class DefaultFeignExcutor extends AbstactFeignTemplateExcutor implements Excutor {

    private AnnotationSetting annotationSetting;

    public DefaultFeignExcutor(AnnotationSetting annotationSetting,Properties properties) {
        super(annotationSetting,properties);
        this.annotationSetting = annotationSetting;
    }


    @Override
    public synchronized Object join() {
        Object data = super.join();
        // 注解标记在了类上
        if (this.annotationSetting instanceof ClassAnnotationSetting){
            Class<?> targetType = getAnnotationSetting().getTargetType();

            if (targetType.isAssignableFrom(Map.class)){
                ClassAnnotationSetting classAnnotationSetting = (ClassAnnotationSetting)this.annotationSetting;
                List<ClassAnnotationProperties> classAnnotationProps = classAnnotationSetting.getFieldSetting();
                Map mapData = (Map) data;
                ArrayList originalObject = (ArrayList) getMybatisQueryResult();
                CopyOnWriteArrayList copyOnWriteOriginalObject = new CopyOnWriteArrayList(originalObject);
                copyOnWriteOriginalObject.forEach(o -> {
                    for (ClassAnnotationProperties classAnnotationprop : classAnnotationProps){
                        ReflectUtils.setObjectProperties(o,classAnnotationprop.getName(),mapData.get(classAnnotationprop.getName()));
                    }

                });
                return originalObject;

            }else {
                throw new RemoteClassNotMatchException("remote class is not match require a map but found a " + targetType.getName());
            }


        }

        Class<?> fieldType = getAnnotationSetting().getResultType();
        Class<?> targetType = getAnnotationSetting().getTargetType();
        String fieldTypeClassName = ExcutorResultMatcher.typeMatch(fieldType.getName());
        String targetTypeClassName = ExcutorResultMatcher.typeMatch(targetType.getName());
        try{

            if (targetTypeClassName.equals(fieldTypeClassName)){
                ArrayList originalObject = (ArrayList) getMybatisQueryResult();
                CopyOnWriteArrayList copyOnWriteOriginalObject = new CopyOnWriteArrayList(originalObject);
                copyOnWriteOriginalObject.forEach(o -> {
                    ReflectUtils.setObjectProperties(o,getAnnotationSetting().getFieldName(),data);
                });
                return originalObject;
            }


        }catch (Exception e){
            throw new RemoteClassNotMatchException("remote class is not match, require a "+fieldTypeClassName+" but found a"+targetTypeClassName,e);
        }

       return getMybatisQueryResult();
    }
}
